#include "UserRegisterSection1.hpp"
#include "MyLogger.hpp"
#include "MySQLclient.hpp"
#include "SaltUtil.hpp"
#include "Configuration.hpp"
#include "nlohmann/json.hpp"
#include <string.h>
#include "func.h"
#include <iostream>
using std::cout;
using std::endl;

namespace wd
{
// 校验用户名格式（与客户端逻辑对齐：非空、≤50字符、仅字母/数字/下划线）
bool UserRegisterSection1::isValidUsername(const string &username)
{
    if(username.empty()||username.size()>50)
    {
        return false;
    }
    for(char c : username)
    {
        if(!isalnum(c)&&c!='_')
        {
            return false;
        }
    }
    return true;
}
// 检查用户名是否已存在（参数化查询防注入）
bool UserRegisterSection1::isUserExists(const string &username)
{
    //连接数据库
    MySQLclient mysql;
    Configuration* conf=Configuration::getInstance();
    if(!mysql.connect(conf->get("db_host"),
                      stoi(conf->get("db_port")),
                      conf->get("db_user"),
                      conf->get("db_pwd"),
                      conf->get("db_name")))
    {
        LOG_INFO("连接数据库失败");
        return false;
    }

    //连接数据库查看用户是否存在并获取盐值
    std::string sql = "SELECT setting FROM user_registry WHERE name = ?"; // 参数化查询防注入
    MYSQL_STMT *stmt=mysql_stmt_init(&mysql._conn);
    if(!stmt||mysql_stmt_prepare(stmt,sql.c_str(),sql.size())!=0)
    {
        LOG_ERROR("查询失败%s",mysql_stmt_error(stmt));
        mysql_stmt_close(stmt);
        return false;
    }
    MYSQL_BIND bind;
    memset(&bind,0,sizeof(bind));
    bind.buffer_type=MYSQL_TYPE_STRING;
    bind.buffer=(char*)username.c_str();
    bind.buffer_length=username.size()+1;
    if(mysql_stmt_bind_param(stmt,&bind)!=0)
    {
        LOG_ERROR("绑定失败%s",mysql_stmt_error(stmt));
        mysql_stmt_close(stmt);
        return false;
    }
    // 执行查询
    if(mysql_stmt_execute(stmt) != 0) {
        LOG_ERROR("执行查询失败: %s", mysql_stmt_error(stmt));  // 修正格式化
        mysql_stmt_close(stmt);
        return false;
    }

    // 新增：检查结果集存储是否成功
    if (mysql_stmt_store_result(stmt) != 0) {
        LOG_ERROR("存储查询结果失败: %s", mysql_stmt_error(stmt));
        mysql_stmt_close(stmt);
        return false; // 存储失败→无法判断，返回false（非用户存在）
    }
    // 绑定结果（不需要实际数据，只需要知道是否有结果）
    int rowCount=mysql_stmt_num_rows(stmt);
    LOG_INFO("查询用户名[%s]，返回行数: %d", username.c_str(), rowCount);
    bool exists = (rowCount> 0);
    //释放资源
    mysql_stmt_close(stmt);
    return exists;

}
void UserRegisterSection1::process()
{
    LOG_INFO("收到注册阶段1请求，类型: %d（预期: %d）", _packet._type, TASK_TYPE_REGISTER_SECTION1);
    //先校验数据包类型客户端登录阶段1的请求
    if(_packet._type!=TASK_TYPE_REGISTER_SECTION1)
    {
        LOG_INFO("阶段1请求失败%d",_packet._type);
        TLV resp(TASK_TYPE_REGISTER_SECTION1_RESP_ERROR,11,"Invalid type");
        _conn->sendInLoop(resp);
        return;
    }

    using json = nlohmann::json;
    string username;
    try {
        json j = json::parse(_packet._msg);
        username = j["username"].get<string>(); // 提取真实用户名
    } catch (...) {
        LOG_ERROR("用户名格式错误（非JSON）：%s", _packet._msg.c_str());
        TLV resp(TASK_TYPE_REGISTER_SECTION1_RESP_ERROR, 15, "Invalid format");
        _conn->sendInLoop(resp);
        return;
    }

    LOG_INFO("阶段1获取用户名%s", username.c_str()); // 日志输出解析后的用户名

    //校验用户名格式
    if(!isValidUsername(username))
    {
        LOG_WARN("校验用户名失败%s",username.c_str());
        TLV resp(TASK_TYPE_REGISTER_SECTION1_RESP_ERROR,15,"Invalid username");
        _conn->sendInLoop(resp);
        return;
    }

    //检验用户名是否已经存在
    if(isUserExists(username))
    {
        LOG_WARN("用户名存在%s",username.c_str());
        TLV resp(TASK_TYPE_REGISTER_SECTION1_RESP_ERROR,15,"Username exit");
        _conn->sendInLoop(resp);
        return;
    }

    //生成盐值构建setting
    string salt=SaltUtil::generateSalt();
    string setting="$1$"+salt+"$";
    LOG_INFO("生成随机盐值: %s (setting: %s)",salt.c_str(),setting.c_str());

    //6. 发送setting给客户端（注册阶段1成功响应，类型）
    TLV resp(TASK_TYPE_REGISTER_SECTION1_RESP_OK, setting.size(), setting.c_str());
    _conn->sendInLoop(resp);
}
}
